#include "ota_version.h"
#include "ota_http_curl.h"
#include  "cJSON.h"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sha.h>
#include "log.h"



// 计算文件的SHA1哈希值
static char* calculate_file_sha1(const char* filename) {
    FILE* file = fopen(filename, "rb");
    if (!file) {
        perror("无法打开文件");
        return NULL;
    }

    unsigned char buffer[4096];
    unsigned char digest[SHA_DIGEST_LENGTH];
    SHA_CTX sha_ctx;

    SHA1_Init(&sha_ctx);

    size_t bytes_read;
    while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) != 0) {
        SHA1_Update(&sha_ctx, buffer, bytes_read);
    }

    SHA1_Final(digest, &sha_ctx);
    fclose(file);

    // 将哈希值转换为十六进制字符串
    char* sha1_string = (char*)malloc(SHA_DIGEST_LENGTH * 2 + 1);
    if (!sha1_string) {
        perror("内存分配失败");
        return NULL;
    }

    for (int i = 0; i < SHA_DIGEST_LENGTH; ++i) {
        sprintf(&sha1_string[i * 2], "%02x", digest[i]);
    }
    sha1_string[SHA_DIGEST_LENGTH * 2 ]= '\0';


    return sha1_string;
}



/**
 * @brief 检查并更新应用程序版本
 * 1  利用 curl 获取ota版本信息(版本号 、sha1验证码)
 * 2  利用 cjson 提取版本json信息的内容  (版本号 、sha1验证码)
 * 3  比较版本号 用当前程序的版本号和远程版本号进行对比 
 * 4  如果本地版本号低 则进行下载
 * 5  利用curl 来下载文件
 * 6  生成本地文件的sha1码 (ai）
 * 7  把本地生成的sha1码和远程的sha1码进行对比
 * 8  如果本地的sha1码和远程的sha1码一致 则下载成功 返回0
 * 9  如果本地的sha1码和远程的sha1码不一致 把下载的文件删除 返回-1
 * 
 * 
 */
int  ota_version_check_update()
{   log_info("开始检查版本更新");
    //1  利用 curl 获取ota版本信息(版本号 、sha1验证码)
     ResponseBody *response_body= ota_http_get(OTA_VERSION_URL);
    // 2  利用 cjson 提取版本json信息的内容  (版本号 、sha1验证码)
    cJSON *root = cJSON_Parse(response_body->str);
    char *ota_sha1= cJSON_GetObjectItem(root, "sha1")->valuestring;
    int ota_major= cJSON_GetObjectItem(root, "major")->valueint;
    int ota_minor= cJSON_GetObjectItem(root, "minor")->valueint;
    int ota_patch= cJSON_GetObjectItem(root, "patch")->valueint;
    // 3  比较版本号 用当前程序的版本号和远程版本号进行对比 
    if(VERSION_MAJOR>ota_major
    ||(VERSION_MAJOR==ota_major && VERSION_MINOR> ota_minor ) 
    ||(VERSION_MAJOR==ota_major && VERSION_MINOR==ota_minor && VERSION_PATCH>ota_patch))
    {   log_info("未发现更高的版本");
        return 0;
    }
    // 4  如果本地版本号低 则进行下载
     log_info("发现更高的版本%d.%d.%d",ota_major,ota_minor,ota_patch);
     //5  利用curl 来下载文件
     unlink(OTA_VERSION_LOCAL_FILE_NAME);
     ota_http_download(OTA_VERSION_DOWNLOAD_URL,OTA_VERSION_LOCAL_FILE_NAME);
     sleep(2);
     //* 6  生成本地文件的sha1码 (ai）
     char *sha1= calculate_file_sha1(OTA_VERSION_LOCAL_FILE_NAME);
     log_info("本地文件的sha1码:%s",sha1);
     log_info("远端的sha1码:%s",ota_sha1);
    //* 7  把本地生成的sha1码和远程的sha1码进行对比
    if(strcmp(sha1,ota_sha1)==0)
    {   
        log_info("下载成功");
        free(sha1);
        free(response_body->str);
        free(response_body);
        cJSON_Delete(root);
        return 0;
    }else{
        log_info("sha1 码不一致,删除文件");
        free(response_body->str);
        free(response_body);
        free(sha1);
        cJSON_Delete(root);
        unlink(OTA_VERSION_LOCAL_FILE_NAME);
        return -1;
    }
    return 0;


}

/**
 * 每日循环不断地检查
 */
int  ota_version_check_update_daily()
{
    while(1)
    {
        sleep(24*60*60);
        ota_version_check_update();
    }
}

// 打印版本信息
int  ota_version_show()
{
    printf("当前版本号:%d.%d.%d\n",VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH);
    return 0;
}